#include "Matt/Vector.h"

#ifndef GL_UTIL_H
#define GL_UTIL_H

// These are slightly smaller than my other
// matrices.  And don't need any modification
// to pass on to OpenGL.
struct mglMatrix {
	float m[16];
};

struct mglNormalVertex {
	float n3f[3];
	float v3f[3];
};

void mglConvertMatrix(mglMatrix *mgl, const Matrix *m);

void mglLoadMatrix(mglMatrix *m);
void mglLoadMatrix(mglMatrix &m);

void mglMultMatrix(mglMatrix *m);
void mglMultMatrix(mglMatrix &m);

void mglMultMatrix(Matrix *m);
void mglMultMatrix(Matrix &m);

void mglLoadMatrix(Matrix *m);
void mglLoadMatrix(Matrix &m);

// Ignores transparency value, for safety.
void mglColor3(Color c);
void mglColor3(unsigned char r, unsigned char g, unsigned char b);

// Uses transparency value.
void mglColor4(Color c);
void mglColor4(unsigned char r, unsigned char g, unsigned char b, unsigned char a);

// Must be called before using above functions,
// if any case color has changed since last call.
void mglColorInit();

struct mglMesh {
	// Mesh drawing and creation must occur between calls to
	// begin and end.  No guarantee that it's save to use VBA's
	// between the two calls, as may be using VBO mode.  Display
	// lists and glVertex and friends should be fine between them.

	// Draw mode must match that used to create all meshes used before
	// end is called.  Note that if mode is VBO and VBO's aren't supported,
	// will change the mode.

	// VBO/VBA state must not be changed at all between these calls.

	// Selecting used to disable changing colors needlessly - very minor speedup, if any.
	static void Begin(unsigned int &drawMode, int selecting);
	static void End();
	static unsigned int currentDrawMode;
	// Used to slightly speed up drawing a mesh twice in a row.
	// Happens most often with cylinders for bonds.  Also
	// can happen with spheres.
	static mglMesh *lastMesh;
	static int selecting;

	mglNormalVertex *vertices;
	int numVertices;
	GLushort *indices;
	int numIndices;
	GLenum glMode;
	// Can't be changed once created.
	// To save memory, if using display listed or VBOs, don't keep a local copy of the mesh.
	int drawMode;
	// List or buffer id.
	GLuint glId;
	// Buffer id for vertex indices.
	GLuint glIndicesId;

	void Draw(Color c);
	void Destroy();
};

mglMesh *CreateMesh(mglNormalVertex *vertices, int numVertices, GLushort *indices, int numIndices, GLenum glMode, int drawMode);

mglMesh *mglMakeSphereMesh(double radius, int res);
mglMesh *mglMakeCylinderMesh(double radius, int res);

#define min(x, y) (x<y?x:y)
#define max(x, y) (x<y?y:x)

#endif
